package com.crm.system.service.impl.returnMoney;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.crm.common.model.DhPageInfo;
import com.crm.common.model.Enum.ResponseCodeEnum;
import com.crm.common.util.*;
import com.crm.dao.mapper.customerManager.CustomerPayMapper;
import com.crm.dao.mapper.orderManager.CustomerProductOrderMapper;
import com.crm.dao.mapper.returnMoney.*;
import com.crm.dao.mapper.sys.UserAccountMapper;
import com.crm.dao.mapper.sys.permissionManagement.SysCompanyMapper;
import com.crm.model.entity.contractManager.CustomerContract;
import com.crm.model.entity.customerManager.CustomerPay;
import com.crm.model.entity.finishOrderProduct.FinishOrderProduct;
import com.crm.model.entity.orderManager.CustomerProductOrder;
import com.crm.model.entity.returnMoney.*;
import com.crm.model.entity.sys.UserAccount;
import com.crm.model.entity.sys.permissionManagement.SysCompany;
import com.crm.model.entity.sys.permissionManagement.SysCompanyExample;
import com.crm.model.qo.returnMoney.BankFlowQO;
import com.crm.model.qo.returnMoney.BankFlowRelateQO;
import com.crm.model.qo.returnMoney.BankFlowRelieveQO;
import com.crm.model.vo.customerContractManager.CustomerContractDetailVO;
import com.crm.model.vo.finance.paymentRecordManager.PaymentRecordExportVO;
import com.crm.model.vo.finishOrderProduct.FinishOrderProductVO;
import com.crm.model.vo.orderManager.CustomerProductOrderVO;
import com.crm.model.vo.orderManager.OrderDetailVO;
import com.crm.model.vo.returnMoney.*;
import com.crm.service.contractManager.CustomerContractDbService;
import com.crm.service.orderManager.CustomerProductOrderDbService;
import com.crm.service.orderManager.CustomerProductOrderDetailDbService;
import com.crm.service.returnMoney.BankFlowDbService;
import com.crm.service.returnMoney.BankFlowWhiteDbService;
import com.crm.system.service.contractManager.CustomerContractService;
import com.crm.system.service.customerManager.CustomerPayService;
import com.crm.system.service.finishOrderProductManager.FinishOrderProductService;
import com.crm.system.service.orderManager.CustomerProductOrderService;
import com.crm.system.service.permissionManagement.SysCompanyService;
import com.crm.system.service.returnMoney.BankFlowService;
import com.crm.system.service.returnMoney.ReturnMoneyService;
import com.crm.system.service.sys.ImportExportService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jsoup.helper.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yuanyunfeng
 * @date 2021/7/26 10:24
 */
@Service
@Slf4j
public class BankFlowServiceImpl implements BankFlowService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private BankFlowDbService bankFlowDbService;
    @Autowired
    private ReturnMoneyService returnMoneyService;
    @Autowired
    private CustomerProductOrderService orderService;
    @Autowired
    private CustomerProductOrderMapper orderMapper;
    @Autowired
    private SysCompanyService companyService;
    @Autowired
    private SysCompanyMapper companyMapper;
    @Autowired
    private ImportExportService importExportService;
    @Autowired
    private CustomerProductOrderDetailDbService customerProductOrderDetailDbService;
    @Autowired
    private BankFlowExamineMapper bankFlowExamineMapper;
    @Autowired
    private ReturnMoneyMapper returnMoneyMapper;
    @Autowired
    private CustomerContractService customerContractService;
    @Autowired
    private FinishOrderProductService finishOrderProductService;
    @Autowired
    private ReturnMoneyLogMapper returnMoneyLogMapper;
    @Autowired
    private BankOrderMapper bankOrderMapper;
    @Autowired
    private CustomerPayService customerPayService;
    @Autowired
    private CustomerPayMapper customerPayMapper;
    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private CustomerContractDbService contractDbService;
    @Autowired
    private CustomerProductOrderDbService orderDbService;
    @Autowired
    private ReturnMoneyExamineMapper returnMoneyExamineMapper;
    @Autowired
    private CustomerProductOrderService customerProductOrderService;
    @Autowired
    private BankFlowWhiteDbService bankFlowWhiteDbService;


    @Override
    @Transactional
    public BankImportVO importBankData(List<BankImportModel> resultList) throws ParseException {
        //当前登陆用户
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        //获取批次号
        if (StringUtils.isBlank(redisUtil.get("bankImportBatchNo"))) {
            redisUtil.set("bankImportBatchNo", "1000");//如果没有则设置初始值
        }
        int batchNo = Integer.valueOf(redisUtil.get("bankImportBatchNo"));
        //将批次号+1
        redisUtil.set("bankImportBatchNo", String.valueOf(batchNo + 1));//有值则+1
        //初始化进度
        int progressBarSchedule = 0;
        BankProcessEntity processEntity = new BankProcessEntity();
        processEntity.setReadRow(0);
        processEntity.setPercent(progressBarSchedule);
        processEntity.setBatchNo(batchNo);
        processEntity.setTotalCount(resultList.size());
        //存redis
        String bankRedisKey = "bankImport_" + userAccount.getAccountId();
        redisUtil.set(bankRedisKey, new Gson().toJson(processEntity));
        //导入标识，true-正常导入，false-页面点击取消 需要中断
        redisUtil.set("bankImportFlag", "true");
        //返回的结果集
        BankImportVO bankImportVO = new BankImportVO();
        //导入成功数量
        int successCount = 0;
        List<BankImportModel> detailList = new ArrayList<>();//错误记录列表
        List<BankImportModel> repeatList = new ArrayList<>();//重复记录
        List<BankFlow> bankFlowSqlList = new ArrayList<>();
        //重复行号
        List<Integer> repeatNos = new ArrayList<>();
        //失败记录
        Integer failureCount = 0;
        //查询数据库的到款日期限制天数
        int termDays = bankFlowDbService.getReturnMoneyDayNum();
        bankImportVO.setTotalCount(resultList.size());
        for (int i = 0; i < resultList.size(); i++) {
            BankImportModel model = resultList.get(i);
            String transactionNo = model.getTransactionNo();
            String transactionDate = model.getTransactionDate();
            String creditMoney = model.getCreditMoney();//金额（可能有逗号）
            if (StringUtils.isNotBlank(creditMoney)) {
                creditMoney = revertMoney(creditMoney).toString();//转换成数值
            }
            BankImportModel detailModel = new BankImportModel();
            BeanUtils.copyProperties(model, detailModel);
            BankImportModel repeatModel = new BankImportModel();
            repeatModel.setTransactionNo(transactionNo);
            repeatModel.setTransactionDate(transactionDate);
            repeatModel.setCreditMoney(creditMoney);
            BankFlow bankFlow = new BankFlow();
            String payeeName = model.getPayeeName();
            //计算修改进度并存放redis保存(1.0 / list.size())为一条数据进度 向上取整
            progressBarSchedule = (int) Math.ceil((1.0 / (resultList.size())) * (i + 1) * 100);
            processEntity.setReadRow(i + 2);
            if (i == resultList.size() - 1) {
                processEntity.setPercent(100);
            } else {
                processEntity.setPercent(progressBarSchedule);
            }
            redisUtil.set(bankRedisKey, new Gson().toJson(processEntity));
            if ("false".equals(redisUtil.get("bankImportFlag"))) {
                log.info("打印点击取消时的结果集是【{}】", new Gson().toJson(bankFlowSqlList));
                redisUtil.delete("bankImportFlag");
                break;
            }
            //必填项校验
            if (StringUtils.isBlank(transactionNo)) {
                detailModel.setErrorReason("交易流水号为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(transactionDate)) {
                detailModel.setErrorReason("交易流日期为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(model.getPayeeAcount())) {
                detailModel.setErrorReason("收款方账号为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (isContainChinese(model.getPayeeAcount())) {
                detailModel.setErrorReason("收款方账号包含中文");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(payeeName)) {
                detailModel.setErrorReason("收款方名称为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(model.getOppositeCompany())) {
                detailModel.setErrorReason("对方单位名称为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            //如果对方单位名称不为空，则判断对方单位名称是否是一串数字
            if (checkIsNumeric(model.getOppositeCompany())) {
                detailModel.setErrorReason("对方单位名称不允许全是数字！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            //如果对方银行账号不为空，则判断是否包含中文
            if (StringUtils.isNotBlank(model.getOppositeBankAccount()) && isContainChinese(model.getOppositeBankAccount())) {
                detailModel.setErrorReason("对方银行账号包含汉字");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(creditMoney)) {
                detailModel.setErrorReason("贷方金额为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isBlank(model.getCompanyName())) {
                detailModel.setErrorReason("所属分公司为空！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            String companyName = model.getCompanyName();
            SysCompany sysCompany = companyService.selectSysCompanyByCompanyName(companyName);
            //校验公司名称是否存在
            if (sysCompany == null) {
                //分公司不存在
                detailModel.setErrorReason("此分公司名称不存在！");
                detailModel.setCompanyName(companyName);
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            String companyId = sysCompany.getCompanyId();
            String trueCompanyName = "";//总公司默认当前公司名称是空
            //3-总公司财务，除了3都是分公司账号
            if (!"3".equals(userAccount.getDeptId())) {
                //分公司
                SysCompany branchCompany = companyService.selectSysCompanyById(userAccount.getCompanyId());
                String branchCompanyName = branchCompany.getCompanyName();
                trueCompanyName = branchCompany.getTrueCompanyName();//公司全称（分公司的收款方名称）
                if (!branchCompanyName.equals(model.getCompanyName())) {
                    //分公司只能导入自己公司的
                    detailModel.setErrorReason("所属分公司错误，请确认当前账号所属分公司与导入的分公司是否一致！");
                    detailList.add(detailModel);
                    failureCount = failureCount + 1;
                    continue;
                }
            }
            //判断 收款方名称
            if (!checkExistPayeeName(model.getPayeeName(), trueCompanyName)) {
                detailModel.setErrorReason("收款名称不存在！");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isNotBlank(transactionNo)) {
                bankFlow.setTransactionNo(model.getTransactionNo());
            }
            if (StringUtils.isNotBlank(transactionDate)) {
                //多个特殊空格或普通空格替换成一个普通空格
                transactionDate = transactionDate.replaceAll("[  ]+", " ");
                //判断交易日期是否符合yyyy-MM-dd HH:mm:ss格式
                if (!DateUtil.isDateTimeVail(transactionDate)) {
                    detailModel.setErrorReason("交易日期格式错误，请检查！");
                    detailList.add(detailModel);
                    failureCount = failureCount + 1;
                    continue;
                } else {
                    //判断 交易日期是否 >= 当前日期 -（数据库里的到款日期天数）
                    Calendar c = Calendar.getInstance();
                    c.add(Calendar.DATE, -termDays);
                    Date date = c.getTime();
                    String preDay = DateUtil.formatDate(date, "yyyy-MM-dd");
                    if (transactionDate.compareTo(preDay) < 0) {
                        detailModel.setErrorReason("交易日期不在回款日期范围内！");
                        detailList.add(detailModel);
                        failureCount = failureCount + 1;
                        continue;
                    }
                    bankFlow.setTransactionDate(transactionDate);
                }
            }
            if (StringUtils.isNotBlank(model.getPayeeAcount())) {//收款方账号
                bankFlow.setPayeeAcount(model.getPayeeAcount());
            }
            if (StringUtils.isNotBlank(payeeName)) {//收款方名称
                bankFlow.setPayeeName(payeeName);
            }
            if (StringUtils.isNotBlank(model.getOppositeCompany())) {//对方单位名称
                bankFlow.setOppositeCompany(model.getOppositeCompany());
            }
            if (StringUtils.isNotBlank(creditMoney)) {//贷方金额
                bankFlow.setCreditMoney(revertMoney(creditMoney));
                bankFlow.setAvailableAmount(revertMoney(creditMoney));//默认可用金额和导入的贷方金额一致
                bankFlow.setUsedAmount(new BigDecimal(0));//默认已用金额是0
            }
            //判断重复记录
            if (repeatList.contains(repeatModel)) {
                int number = i + 2;
                log.info("第" + number + "行记录在文件中已存在！");
                repeatNos.add(number);
                //重复标识
                detailModel.setErrorReason("重复数据");
                detailModel.setIsRepeat("Y");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            repeatList.add(repeatModel);
            //根据transaction_no（交易流水号）、交易日期、金额 查询数据库是否存在
            boolean existTransactioNo = bankFlowDbService.existTransactioNo(transactionNo, transactionDate, creditMoney);
            if (existTransactioNo) {
                repeatNos.add(i + 2);
                //重复标识(数据库的重复)
                detailModel.setErrorReason("重复数据");
                detailModel.setIsRepeat("Y");
                detailList.add(detailModel);
                failureCount = failureCount + 1;
                continue;
            }
            if (StringUtils.isNotBlank(model.getAbstracts())) {
                bankFlow.setAbstracts(model.getAbstracts());
            }
            if (StringUtils.isNotBlank(model.getOppositeBank())) {
                bankFlow.setOppositeBank(model.getOppositeBank());
            }
            if (StringUtils.isNotBlank(model.getOppositeBankAccount())) {
                bankFlow.setOppositeBankAccount(model.getOppositeBankAccount());
            }
            bankFlow.setRelationState("N");//默认为N-未关联
            bankFlow.setCreatePeopleId(userAccount.getAccountId());//创建人
            bankFlow.setCreatePeopleName(userAccount.getUserName());//创建人名称
            bankFlow.setFlowId(CommonUtils.getGUID());//主键id
            bankFlow.setRowNumber(i + 2);//行号
            bankFlow.setBatchNo(batchNo);//批次号
            bankFlow.setCompanyName(companyName);//所属分公司名称
            bankFlow.setCompanyId(companyId);//所属分公司id
            bankFlow.setOperateFlag("ok");
            bankFlowSqlList.add(bankFlow);
        }
        //判断完成 入库
        if (bankFlowSqlList != null && bankFlowSqlList.size() > 0) {
            for (BankFlow bk : bankFlowSqlList) {
                int count = bankFlowDbService.insertBankFlow(bk);
                if (count > 0) {
                    successCount = successCount + 1;
                }
            }
        }
        bankImportVO.setSuccessCount(successCount);
        bankImportVO.setFailureCount(failureCount);
        bankImportVO.setRepeatNumber(repeatNos);
        bankImportVO.setBankDetail(detailList);
        //插入导入表
        if (successCount > 0) {
            importExportService.insertExportService(successCount, "1", "1", "6");
        }
        //入库完成后将redis的进度、导入标识删除
        redisUtil.delete(bankRedisKey);
        redisUtil.delete("bankImportFlag");
        return bankImportVO;
    }


    /**
     * 金额格式转换，字符串转换成数值
     *
     * @param str
     * @return
     */
    public static BigDecimal revertMoney(String str) {
        DecimalFormat format = new DecimalFormat();
        format.setParseBigDecimal(true);
        ParsePosition position = new ParsePosition(0);
        BigDecimal parse = (BigDecimal) format.parse(str, position);
        if (str.length() == position.getIndex()) {
            return parse;
        }
        return null;
    }


    @Override
    public AssociatedOrderVO queryByOrderNumber(String productOrderId, Integer pageIndex, Integer pageSize) {
        AssociatedOrderVO associatedOrderVO = new AssociatedOrderVO();

        //订单详情
        FinanceProductOderInfoVO orderInfoVO = customerProductOrderService.financeProductOderInfo(productOrderId, null);
//        OrderDetailVO orderDetailVO = orderService.selectOrderDetailVO(productOrderId);
        //产品
        DhPageInfo<FinishOrderProductVO> finishProducts = finishOrderProductService.selectOrderFinishProduct(productOrderId, pageIndex, pageSize);
        //合同
        FinanceProductOderInfoVO products = orderService.financeProductOderInfo(productOrderId, null);
        CustomerContractDetailVO customerContractDetailVO = customerContractService.selectCustomerContractVODetail(products.getContractId());
        if (Objects.nonNull(customerContractDetailVO)) {
            //隐藏客户信息
            customerContractDetailVO.setContactName(null);
            customerContractDetailVO.setContactDetails(null);
            customerContractDetailVO.setCustomerEmail(null);
        }
        associatedOrderVO.setProductOrderId(productOrderId);
        associatedOrderVO.setOrderDetailVO(orderInfoVO);
        associatedOrderVO.setContract(customerContractDetailVO);
        associatedOrderVO.setProductList(finishProducts);
        return associatedOrderVO;
    }


    @Synchronized
    @Transactional
    @Override
    public Map<String, String> relatedOrder(BankFlowRelateQO relateQO) throws ParseException {
        String transactionDate = relateQO.getTransactionDate();
        String transactionNo = relateQO.getTransactionNo();
        BigDecimal creditMoney = relateQO.getCreditMoney();
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isBlank(transactionNo) || StringUtils.isBlank(transactionDate) || StringUtils.isBlank(creditMoney.toString())) {
            map.put("code", ResponseCodeEnum.PARAMETER_MISSING.getResponseCode());
            map.put("message", ResponseCodeEnum.PARAMETER_MISSING.getResponseValue());
            return map;
        }
        BankFlow bankFlow = bankFlowDbService.selectByFlowId(relateQO.getFlowId());
        bankFlow.setOppositeCompany(relateQO.getPaymentUnit());//付款单位
        bankFlow.setOppositeBankAccount(relateQO.getPaymentAccount());//付款账号
        bankFlow.setOppositeBank(relateQO.getPaymentBank());//付款银行
        BigDecimal availableAmountOld = bankFlow.getAvailableAmount();//数据库原来的可用金额
        BigDecimal usedAmountOld = bankFlow.getUsedAmount();//数据库原来的已用金额
        //判断金额 可用金额>=传入的到款金额
        int compareTo = availableAmountOld.compareTo(relateQO.getArriveMoney());
        if (compareTo == (-1)) {
            map.put("code", ResponseCodeEnum.BALANCE_NOT_ENOUGH.getResponseCode());
            map.put("message", ResponseCodeEnum.BALANCE_NOT_ENOUGH.getResponseValue());
            return map;
        }
        BankFlowRecord record = new BankFlowRecord();
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登陆用户
        Integer arriveAccountType = relateQO.getArriveAccountType();
        //关联客户充值
        if ("F".equals(relateQO.getRelateType()) && StringUtils.isNotBlank(relateQO.getCustomerPayId())) {
            //判断所属公司是否是同一个
            boolean isTheSameCompany = checkTheSameName(bankFlow.getFlowId(), bankFlow.getTransactionNo(), null, null, relateQO.getCustomerPayId(), bankFlow.getCompanyName());
            if (!isTheSameCompany) {
                map.put("code", ResponseCodeEnum.BANK_RELATE_COMPANY_ERROR.getResponseCode());
                map.put("message", ResponseCodeEnum.BANK_RELATE_COMPANY_ERROR.getResponseValue());
                return map;
            }
            //映射到款账号类型名称
            String arriveUnitName = revertArriveAccountType(arriveAccountType, bankFlow.getPayeeName());
            bankFlow.setPayeeName(arriveUnitName);//收款名称（到款账号类型）
            CustomerPay customerPay = new CustomerPay();
            customerPay.setChsCustomerPayId(relateQO.getCustomerPayId());
            customerPay.setPayMoney(relateQO.getArriveMoney());//充值金额
            customerPay.setPaymentDate(DateUtils.parse(relateQO.getTransactionDate(), "yyyy-MM-dd HH:mm:ss"));
            customerPay.setPaymentUnit(relateQO.getPaymentUnit());//付款单位
            customerPay.setCustomerId(relateQO.getCustomerId());
            customerPay.setArriveMethod(0);//银行回款
            customerPay.setPaymentAccount(relateQO.getPaymentAccount());//付款账号
            customerPay.setPaymentBank(relateQO.getPaymentBank());//付款银行
            customerPay.setPaymentSerial(relateQO.getTransactionNo());//流水号
            customerPay.setArriveAccountType(arriveAccountType);//到款账号类型
            customerPay.setArriveUnitName(arriveUnitName);
            customerPay.setPayType(relateQO.getPayType());
            customerPay.setRemark(relateQO.getRemark());
            //调用确认收款接口
            customerPayService.notarizeCustomerPay(customerPay);
            //可用金额 做减
            BigDecimal availableAmount = availableAmountOld.subtract(relateQO.getArriveMoney());
            bankFlow.setAvailableAmount(availableAmount);
            if (availableAmount.compareTo(BigDecimal.ZERO) == 0) {
                //如果可用金额为0 则关联状态为 已关联
                bankFlow.setRelationState("Y");
            } else {
                bankFlow.setRelationState("B");//部分关联
            }
            //已用金额 做加
            bankFlow.setUsedAmount(usedAmountOld.add(relateQO.getArriveMoney()));
            //插入关联表和 轨迹表
            insertBankOrderAndLog(null, relateQO.getArriveMoney(), relateQO);
            map.put("code", ResponseCodeEnum.OK.getResponseCode());
        }
        //关联订单
        if ("D".equals(relateQO.getRelateType()) && StringUtils.isNotBlank(relateQO.getProductOrderId())) {
            //查询订单是否在审核
            CustomerProductOrder order = orderDbService.selectCustomerProductOrderById(relateQO.getProductOrderId());
            if (order.getExamineState() != null && order.getExamineState() == 1) {
                map.put("code", ResponseCodeEnum.BANK_FLOW_RELATE_ORDER_EAMING.getResponseCode());
                map.put("message", ResponseCodeEnum.BANK_FLOW_RELATE_ORDER_EAMING.getResponseValue());
                return map;
            }
            ReturnMoney req = new ReturnMoney();
            req.setOrderId(relateQO.getProductOrderId());
            req.setArriveMoney(relateQO.getArriveMoney());//到款金额
            req.setArriveTime(DateUtils.parse(relateQO.getTransactionDate()));//交易日期
            req.setPaymentUnit(relateQO.getPaymentUnit());//付款单位
            req.setPaymentAccount(relateQO.getPaymentAccount());//付款账号
            req.setPaymentBank(relateQO.getPaymentBank());//付款银行
            req.setArriveMethod(0);//到款方式-银行回款
            req.setArriveAccountType(arriveAccountType);//到款账号类型
            req.setArriveUnitName(bankFlow.getPayeeName());//到款账号名称
            req.setSerial(relateQO.getTransactionNo());//流水号
            req.setArriveType(relateQO.getArriveType());//到款类型 0-全部，1-部分
            req.setFinishOrderProductNum(relateQO.getFinishOrderProductNum());//产品号
            req.setFinishOrderProductId(relateQO.getFinishOrderProductId());//产品号id
            req.setProductName(relateQO.getProductName());//产品名称
            req.setProductCategories(relateQO.getProductCategories());
            req.setProductId(relateQO.getProductId());
            req.setProductNumber(relateQO.getProductCode());
            req.setOrderDetailType(relateQO.getOrderDetailType());
            boolean preReturnMoneyFlag = false;//是否预回款标识
            String orderCustomerName = order.getCustomerName();
            String oppositeCompany = bankFlow.getOppositeCompany();
            CustomerContract customerContract = contractDbService.selectContractById(order.getContractId());
            String contractType = customerContract.getContractType();
            //如果流水对方单位名称和订单客户名称不一样、并且流水对方单位名称>4个字则走预回款逻辑 、并且是会员合同
            if (!oppositeCompany.equals(orderCustomerName) && oppositeCompany.length() > 4 && ("2".equals(contractType) || "4".equals(contractType) || "7".equals(contractType))) {
                preReturnMoneyFlag = true;
                //查询白名单表中是否存在该条记录
                if (bankFlowWhiteDbService.queryExistWhiteListName(oppositeCompany)) {
                    preReturnMoneyFlag = false;//特殊判断，如果这个对方单位名称存在白名单配置中，不走预回款
                }
            }
            //那到订单id调用/addReturnMoney的接口
            Map<String, Object> returnMoneyResult = returnMoneyService.mergeAddReturnMoneyMethod(req, 1, preReturnMoneyFlag);
            String code = returnMoneyResult.get("code").toString();
            List<String> returnMoneyIdList = (List<String>) returnMoneyResult.get("returnMoneyIds");
            map.put("code", code);
            if (ResponseCodeEnum.OK.getResponseCode().equals(code)) {
                record.setErrorMessage("关联成功");
                record.setRelationState("Y");
                //可用金额 做减
                BigDecimal availableAmount = availableAmountOld.subtract(relateQO.getArriveMoney());
                bankFlow.setAvailableAmount(availableAmount);
                if (availableAmount.compareTo(BigDecimal.ZERO) == 0) {
                    //如果可用金额为0 则关联状态为 已关联
                    bankFlow.setRelationState("Y");
                } else {
                    bankFlow.setRelationState("B");//部分关联
                }
                //已用金额 做加
                bankFlow.setUsedAmount(usedAmountOld.add(relateQO.getArriveMoney()));
                //往return_money_log插入一条记录
                if (returnMoneyIdList != null && returnMoneyIdList.size() > 0) {
                    for (int i = 0; i < returnMoneyIdList.size(); i++) {
                        String returnMoneyId = returnMoneyIdList.get(i);
                        ReturnMoneyVO returnMoenyInfoById = returnMoneyMapper.getReturnMoenyInfoById(returnMoneyId);
                        BigDecimal arriveMoney = returnMoenyInfoById.getArriveMoney();
                        insertBankOrderAndLog(returnMoneyId, arriveMoney, relateQO);

                        //判断客户名称和对方单位名称是否是一个，如果不是则修改状态为预回款
                        if (preReturnMoneyFlag) {
                            checkTheSameName(bankFlow.getFlowId(), bankFlow.getTransactionNo(), relateQO.getProductOrderId(), returnMoneyId, null, oppositeCompany);
                            map.put("code", ResponseCodeEnum.BANK_RELATE_SUCCESS_PRE_RETURNMONEY.getResponseCode());
//                            map.put("message", "当前流水的对方单位名称与关联订单的客户名称不一致，触发审核，当前回款为预回款");
                        }
                    }
                }
            } else {
                //调用回款接口失败失败
                record.setRelationState("N");
                bankFlow.setRelationState("N");//设置为未关联
                //失败原因
                if ("RM0002".equals(code)) {
                    record.setErrorMessage(ResponseCodeEnum.RNTURN_MONEY_TOOBIG.getResponseValue());
                } else if ("RM0003".equals(code)) {
                    record.setErrorMessage(ResponseCodeEnum.RNTURN_MONEY_REVIEW.getResponseValue());
                } else if ("RM0004".equals(code)) {
                    record.setErrorMessage(ResponseCodeEnum.RNTURN_MONEY_ABOLISH.getResponseValue());
                }
            }
            record.setId(CommonUtils.getGUID());
            record.setTransactionNo(transactionNo);
            record.setProductOrderId(relateQO.getProductOrderId());
            record.setCreatePeopleId(userAccount.getAccountId());
            bankFlowDbService.insertBankFlowRecord(record);
        }
        //更新银行导入流水表数据
        bankFlowDbService.updateRelationState(bankFlow);
        return map;
    }


    /**
     * @return boolean
     * @author yuanyunfeng
     * @Description 校验收款方名称是否存在
     * @date 2021/11/23 10:11
     * @Param [payeeName]
     **/
    private boolean checkExistPayeeName(String payeeName, String currentTrueCompanyName) {
        List<String> payeeNameList = new ArrayList<>();
        payeeNameList.add("北京财税研究院");
        payeeNameList.add("大成方略网络科技有限公司");
        payeeNameList.add("北京大成方略财务顾问有限公司");
        payeeNameList.add("北京大成方略纳税人俱乐部有限公司");
        payeeNameList.add("大成方略纳税人俱乐部股份有限公司");
        boolean contains = payeeNameList.contains(payeeName);
        boolean flag = false;
        if (contains) {
            flag = true;
        } else {
            //如果不是以上五个则查询数据库
            SysCompanyExample companyExample = new SysCompanyExample();
            companyExample.createCriteria().andTrueCompanyNameEqualTo(payeeName).andDeleteStatusEqualTo(Short.valueOf("0"));
            List<SysCompany> sysCompanies = companyMapper.selectByExample(companyExample);
            if (sysCompanies != null && sysCompanies.size() > 0) {
                flag = true;//数据库存在收款方名称
            }
            //数据库存在，则判断名称和当前登录用户所属的trueCompanyName是否一致（分公司时判断）
            if (StringUtils.isNotBlank(currentTrueCompanyName)) {
                if (payeeName.equals(currentTrueCompanyName)) {
                    flag = true;
                }
            }
        }
        return flag;
    }


    /**
     * @return java.lang.String
     * @author yuanyunfeng
     * @Description 根据到款账号类型映射中文名字
     * @date 2021/11/16 14:26
     * @Param [arriveAccountType, payeeName]
     **/
    private String revertArriveAccountType(Integer arriveAccountType, String bankPayeeName) {
        if (arriveAccountType == 1) {
            return "北京财税研究院";
        } else if (arriveAccountType == 2) {
            return "大成方略网络科技有限公司";
        } else if (arriveAccountType == 3) {
            return "北京大成方略财务顾问有限公司";
        } else if (arriveAccountType == 4) {
            return "北京大成方略纳税人俱乐部有限公司";
        } else if (arriveAccountType == 5) {
            return "大成方略纳税人俱乐部股份有限公司";
        } else {
            UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登陆用户
            if ("3".equals(userAccount.getDeptId())) {
                return bankPayeeName;//总公司则用流水本身的0-对应的分公司名称
            } else {
                //分公司
                String trueCompanyName = companyService.selectSysCompanyById(userAccount.getCompanyId()).getTrueCompanyName();
                return trueCompanyName;
            }

        }
    }


    /**
     * @return boolean
     * @author yuanyunfeng
     * @Description 判断流水<对方单位名称>和订单<所属客户名称>是否一致
     * 如果不一致则修改 订单表、回款表、finsh表、合同表、流水表的状态为预回款
     * @date 2021/11/26 13:58
     * @Param [flowId, transactionNo, orderId, returnMoneyId, customerPayId, flowCompareName]
     **/
    private boolean checkTheSameName(String flowId, String transactionNo, String orderId, String returnMoneyId, String customerPayId, String flowCompareName) {
        if (StringUtils.isNotBlank(orderId)) {
            CustomerProductOrder customerProductOrder = new CustomerProductOrder();
            CustomerProductOrderVO order = orderService.getOrderInfoById(orderId);
            String affiliationCompanyId = order.getAffiliationCompanyId();
            BeanUtils.copyProperties(order, customerProductOrder);
            String orderCustomerName = order.getCustomerName();
            if (!flowCompareName.equals(orderCustomerName)) {
                //订单所属分公司和流水所属分公司不是同一个
                ReturnMoney returnMoney = new ReturnMoney();
                ReturnMoneyVO returnMoenyInfoById = returnMoneyMapper.getReturnMoenyInfoById(returnMoneyId);
                BeanUtils.copyProperties(returnMoenyInfoById, returnMoney);
                returnMoney.setReturnStatus(0);//预回款
                returnMoney.setExamState(1);//审核中
                returnMoneyMapper.updateReturnMoney(returnMoney);
                String finishOrderProductId = returnMoney.getFinishOrderProductId();
                if (StringUtils.isNotBlank(finishOrderProductId)) {
                    FinishOrderProduct finishOrderProduct = finishOrderProductService.selectFinishOrderProductById(finishOrderProductId);
                    finishOrderProduct.setProductStatus("6");//预回款
                    finishOrderProductService.updateFinishOrderProduct(finishOrderProduct);
                }
                String contractId = returnMoney.getContractId();
                CustomerContract customerContract = contractDbService.selectContractById(contractId);
                customerContract.setPaymentStatus("4");//预回款
                customerContract.setContractStatus("1");//未生效
                contractDbService.updateByPrimaryKey(customerContract);
                customerProductOrder.setOrderStatus("5");//预回款
                orderDbService.updateOrderCustom(customerProductOrder);
                BankOrderExample bankOrderExample = new BankOrderExample();
                bankOrderExample.createCriteria().andFlowIdEqualTo(flowId).andReturnMoneyIdEqualTo(returnMoneyId).andDelFlagEqualTo(0);
                List<BankOrder> bankOrders = bankOrderMapper.selectByExample(bankOrderExample);
                if (bankOrders != null && bankOrders.size() > 0) {
                    for (BankOrder bo : bankOrders) {
                        bo.setReturnStatus(0);
                        bankOrderMapper.updateByPrimaryKeySelective(bo);
                    }
                }
                //回款审核表新增记录
                UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登陆用户
                ReturnMoneyExamine returnMoneyExamine = new ReturnMoneyExamine();
                returnMoneyExamine.setExamineId(CommonUtils.getGUID());
                returnMoneyExamine.setFlowId(flowId);
                returnMoneyExamine.setTransactionNo(transactionNo);
                returnMoneyExamine.setProductOrderId(orderId);
                returnMoneyExamine.setReturnMoneyId(returnMoneyId);
                returnMoneyExamine.setFinishOrderProductNum(returnMoney.getFinishOrderProductNum());
                returnMoneyExamine.setApplyPeopleId(userAccount.getAccountId());
                returnMoneyExamine.setApplyTime(new Date());
                returnMoneyExamine.setCompanyId(affiliationCompanyId);//所属分公司(订单所属分公司)
                returnMoneyExamineMapper.insertSelective(returnMoneyExamine);

                return false;//返回标识 不是同一个客户名称
            }
        }
        //客户充值的判断
        if (StringUtils.isNotBlank(customerPayId)) {
            CustomerPay customerPay = customerPayMapper.selectByPrimaryKey(customerPayId);
            String createPeopleId = customerPay.getCreatePeopleId();
            UserAccount payUser = userAccountMapper.selectByPrimaryKey(createPeopleId);
            String payCompanyName = companyMapper.selectByPrimaryKey(payUser.getCompanyId()).getCompanyName();
            if (!flowCompareName.equals(payCompanyName)) {
                return false;
            }
        }
        return true;
    }


    /**
     * @return boolean
     * @author yuanyunfeng
     * @Description 判断一个字符串是不是全是数字
     * @date 2021/11/29 15:44
     * @Param [str]
     **/
    private boolean checkIsNumeric(String str) {
        for (int i = str.length(); --i >= 0; ) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串中是否包含中文
     *
     * @param str 待校验字符串
     * @return 是否为中文
     * @warn 不能校验是否为中文标点符号
     */
    private boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }


    /**
     * @return void
     * @author yuanyunfeng
     * @Description 关联成功后新增log表记录和bank_order表记录
     * @date 2021/11/10 18:12
     * @Param [returnMoneyId, relateQO]
     **/
    private void insertBankOrderAndLog(String returnMoneyId, BigDecimal arriveMoney, BankFlowRelateQO relateQO) {
        ReturnMoneyLog moneyLog = new ReturnMoneyLog();
        moneyLog.setReturnMoneyLogId(CommonUtils.getGUID());
        if (StringUtils.isNotBlank(relateQO.getCustomerPayId())) {
            moneyLog.setCustomerPayId(relateQO.getCustomerPayId());//客户充值id
        }
        if (StringUtils.isNotBlank(returnMoneyId)) {
            moneyLog.setReturnMoneyId(returnMoneyId);//回款id
        }
        moneyLog.setFormerData("0");//新数据 原来的写0
        moneyLog.setFlowId(relateQO.getFlowId());
        moneyLog.setNewData(arriveMoney.toString());
        moneyLog.setOperatorType(4);//4-关联
        moneyLog.setCreateTm(new Date());
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        moneyLog.setCreatePeopleId(userAccount.getAccountId());
        returnMoneyLogMapper.insert(moneyLog);
        //往流水订单关联表插入记录记录
        BankOrder bankOrder = new BankOrder();
        bankOrder.setId(CommonUtils.getGUID());
        bankOrder.setFlowId(relateQO.getFlowId());
        bankOrder.setOrderId(relateQO.getProductOrderId());
        bankOrder.setOrderNumber(relateQO.getOrderNumber());
        bankOrder.setCreatePeopleId(userAccount.getAccountId());
        //判断关联类型是订单还是客户充值
        if (StringUtils.isNotBlank(relateQO.getCustomerPayId())) {
            bankOrder.setRelateType("F");
            bankOrder.setCustomerPayId(relateQO.getCustomerPayId());
            bankOrder.setPayNumber(relateQO.getPayNumber());
        } else {
            bankOrder.setRelateType("D");
            bankOrder.setReturnMoneyId(returnMoneyId);
        }
        bankOrderMapper.insertSelective(bankOrder);
    }


    @Override
    public BankProcessEntity queryUploadProcess() {
        //当前登陆用户
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        String processKey = "bankImport_" + userAccount.getAccountId();
        String result = redisUtil.get(processKey);
//        log.info("打印本次读取到的百分比结果【{}】", result);
        BankProcessEntity processEntity = new Gson().fromJson(result, BankProcessEntity.class);
        return processEntity;
    }

    @Override
    public String cancelUpload(String readRow) throws InterruptedException {
        //当前登陆用户
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
        String processKey = "bankImport_" + userAccount.getAccountId();
        String redisValue = redisUtil.get(processKey);
        BankProcessEntity processEntity = new Gson().fromJson(redisValue, BankProcessEntity.class);
        String state = processEntity.getState();
        if (processEntity != null) {
            int percent = processEntity.getPercent();
            if (percent == 100) {
                redisUtil.delete(processKey);
                return "数据已加载完成，不允许取消";
            }
            int stopReadRow = processEntity.getReadRow();
            if (StringUtils.isNotBlank(readRow)) {
                stopReadRow = Integer.valueOf(readRow);
            }
            log.info("打印暂停的行号是【{}】,返回的状态是【{}】", stopReadRow, state);
            //将bankImportFlag标识置为false
            redisUtil.set("bankImportFlag", "false");
            redisUtil.delete(processKey);
        }

        return "操作成功";
    }

    @Override
    public DhPageInfo<BankFlowQueryVO> queryBankFlowData(Integer pageIndex, Integer pageSize, String sortName, String sortOrder, BankFlowQO bankFlowQO) {
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        String currentCompanyId = "";
        String createPeopleId = "";
        if (!"3".equals(userAccount.getDeptId())) {
            currentCompanyId = userAccount.getCompanyId();//3-总公司财务，除了3都是分公司账号
            createPeopleId = userAccount.getAccountId();
        }
        List<BankFlowQueryVO> queryList = bankFlowDbService.queryBankList(currentCompanyId, bankFlowQO);
        PageInfo<BankFlowQueryVO> pageInfo = new PageInfo<BankFlowQueryVO>(queryList);
        return new DhPageInfo<BankFlowQueryVO>(pageInfo, queryList);
    }

    @Override
    public BankFlowDataVO queryMonthMonthTotal(String queryYear, String queryMonth) {
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        String isBranchCompany = "";
        String createPeopleId = "";
        String companyId = "";
        if (!"3".equals(userAccount.getDeptId())) {
            isBranchCompany = "Y";
            createPeopleId = userAccount.getAccountId();
            companyId = userAccount.getCompanyId();
        }
        BankFlowDataVO bankFlowDataVO = bankFlowDbService.queryMonthMoney(createPeopleId, queryYear, queryMonth);
        bankFlowDataVO.setIsBranchCompany(isBranchCompany);
        bankFlowDataVO.setCompanyId(companyId);
        return bankFlowDataVO;
    }

    @Override
    public DhPageInfo<BankFlowRelateVO> queryBankRelatedByFlowId(Integer pageIndex, Integer pageSize, String flowId) {
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        List<BankFlowRelateVO> relatedList = bankFlowDbService.queryBankRelatedByFlowId(flowId);
        PageInfo<BankFlowRelateVO> pageInfo = new PageInfo<BankFlowRelateVO>(relatedList);
        return new DhPageInfo<BankFlowRelateVO>(pageInfo, relatedList);
    }

    @Override
    public DhPageInfo<BankFlowReturnLogVO> queryOperatorLog(Integer pageIndex, Integer pageSize, String flowId, String orderNumber, String payNumber) {
        List<BankFlowReturnLogVO> returnLogs = new ArrayList<>();
        List<BankFlowReturnLogVO> res = new ArrayList<>();
        //查询订单的
        if (StringUtils.isNotBlank(orderNumber)) {
            if (pageIndex != null && pageSize != null) {
                PageHelper.startPage(pageIndex, pageSize);
            }
            returnLogs = bankFlowDbService.queryOperatorLog(flowId, orderNumber);
            PageInfo<BankFlowReturnLogVO> pageInfo = new PageInfo<BankFlowReturnLogVO>(returnLogs);
            return new DhPageInfo<BankFlowReturnLogVO>(pageInfo, returnLogs);
        } else if (StringUtils.isNotBlank(payNumber)) {
            if (pageIndex != null && pageSize != null) {
                PageHelper.startPage(pageIndex, pageSize);
            }
            //查询客户充值的
            returnLogs = bankFlowDbService.queryCustomerPayLog(flowId, payNumber);
            PageInfo<BankFlowReturnLogVO> pageInfo = new PageInfo<BankFlowReturnLogVO>(returnLogs);
            return new DhPageInfo<BankFlowReturnLogVO>(pageInfo, returnLogs);
        } else {
            List<BankFlowReturnLogVO> orderList = bankFlowDbService.queryOperatorLog(flowId, orderNumber);
            List<BankFlowReturnLogVO> payList = bankFlowDbService.queryCustomerPayLog(flowId, payNumber);
            List<BankFlowReturnLogVO> subAvailableAmountList = bankFlowDbService.querySubAvailableAmount(flowId);
            returnLogs.addAll(orderList);
            returnLogs.addAll(payList);
            returnLogs.addAll(subAvailableAmountList);
            res = PageUtil.startPage(returnLogs, pageIndex, pageSize);
            PageInfo<BankFlowReturnLogVO> pageInfo = new PageInfo<BankFlowReturnLogVO>(returnLogs);
            return new DhPageInfo<BankFlowReturnLogVO>(pageInfo, res);
        }


    }

    @Override
    public DhPageInfo<BankOrderReturn> queryReturnMoney(Integer pageIndex, Integer pageSize, String flowId, String orderNumber, String payNumber) {
        if (pageIndex != null && pageSize != null) {
            PageHelper.startPage(pageIndex, pageSize);
        }
        List<BankOrderReturn> returnMoneyList = new ArrayList<>();
        if (StringUtils.isNotBlank(orderNumber)) {
            returnMoneyList = bankFlowDbService.queryReturnMoney(flowId, orderNumber);
        }
        if (StringUtils.isNotBlank(payNumber)) {
            returnMoneyList = bankFlowDbService.queryPayMoney(flowId, payNumber);
        }

        PageInfo<BankOrderReturn> pageInfo = new PageInfo<BankOrderReturn>(returnMoneyList);
        return new DhPageInfo<BankOrderReturn>(pageInfo, returnMoneyList);
    }

    @Override
    public String relieveBank(BankFlowRelieveQO relieveQO) {
        String flowId = relieveQO.getFlowId();
        String returnMoneyId = relieveQO.getReturnMoneyId();
        if (StringUtils.isBlank(flowId)) {
            return "请输入需要解除关联的记录id";
        }
        if (StringUtils.isBlank(relieveQO.getReason())) {
            return "请输入解除关联原因！";
        }
        //判断回款是否封账
        if (StringUtils.isNotBlank(relieveQO.getReturnMoneyId())) {
            ReturnMoneyVO returnMoenyInfoById = returnMoneyMapper.getReturnMoenyInfoById(relieveQO.getReturnMoneyId());
            Integer closeStatus = returnMoenyInfoById.getCloseStatus();
            if (closeStatus == 1) {
                return "该笔到款已封账，无法解除关联！";
            }
        }
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        BankFlow bk = bankFlowDbService.selectByFlowId(flowId);
        String relationState = bk.getRelationState();
        //关联状态是 已关联/部分关联才能 点击解除关联
        if ("Y".equals(relationState) || "B".equals(relationState)) {
            BankFlowExamine examine = new BankFlowExamine();
            examine.setExamineId(CommonUtils.getGUID());
            examine.setRelationId(flowId);
            examine.setTransactionNo(bk.getTransactionNo());
            if (StringUtils.isNotBlank(relieveQO.getOrderId())) {
                examine.setProductOrderId(relieveQO.getOrderId());
            }
            if (StringUtils.isNotBlank(relieveQO.getProductName())) {
                examine.setProductName(relieveQO.getProductName());
            }
            if (StringUtils.isNotBlank(relieveQO.getCustomerPayId())) {
                examine.setCustomerPayId(relieveQO.getCustomerPayId());
            }
            examine.setFinishOrderProductNum(relieveQO.getFinishOrderProductNum());
            examine.setReturnMoneyId(returnMoneyId);
            examine.setRelationReason(relieveQO.getReason());
            examine.setApplyPeopleId(userAccount.getAccountId());
            examine.setApplyTime(new Date());
            examine.setCompanyId(userAccount.getCompanyId());
            bankFlowExamineMapper.insertSelective(examine);
            //修改回款表的审核状态为1
            if (StringUtils.isNotBlank(returnMoneyId)) {
                ReturnMoney returnMoney = new ReturnMoney();
                returnMoney.setReturnMoneyId(returnMoneyId);
                returnMoney.setExamState(1);
                returnMoneyMapper.updateReturnMoney(returnMoney);
            }
            //修改客户充值的审核状态为1
            if (StringUtils.isNotBlank(relieveQO.getCustomerPayId())) {
                CustomerPay customerPay = new CustomerPay();
                customerPay.setChsCustomerPayId(relieveQO.getCustomerPayId());
                customerPay.setExamState(1);
                customerPayMapper.updateByPrimaryKeySelective(customerPay);
            }
        } else {
            return "该单流水未关联无法解除关联!";
        }
        return "操作完成";
    }

    @Override
    public String queryOrderId(String orderNumber) {
        return bankFlowDbService.queryOrderId(orderNumber);
    }

    @Override
    public BankFlowQueryVO selectByFlowId(String flowId) {
        BankFlow bankFlow = bankFlowDbService.selectByFlowId(flowId);
        BankFlowQueryVO queryVO = new BankFlowQueryVO();
        BeanUtils.copyProperties(bankFlow, queryVO);
        String payeeName = queryVO.getPayeeName();
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        if ("北京财税研究院".equals(payeeName)) {
            queryVO.setPayeeName("1");
        } else if ("大成方略网络科技有限公司".equals(payeeName)) {
            queryVO.setPayeeName("2");
        } else if ("北京大成方略财务顾问有限公司".equals(payeeName)) {
            queryVO.setPayeeName("3");
        } else if ("北京大成方略纳税人俱乐部有限公司".equals(payeeName)) {
            queryVO.setPayeeName("4");
        } else if ("大成方略纳税人俱乐部股份有限公司".equals(payeeName)) {
            queryVO.setPayeeName("5");
        } else {
            queryVO.setPayeeName("0");
            if ("3".equals(userAccount.getDeptId())) {
                queryVO.setCurrentTrueCompanyName(bankFlow.getPayeeName());//如果是总公司则返回当前流水的名称
            } else {
                //如果是分公司
                SysCompany sysCompany = companyService.selectSysCompanyById(userAccount.getCompanyId());
                if (sysCompany != null) {
                    String trueCompanyName = sysCompany.getTrueCompanyName();//分公司全称
                    queryVO.setCurrentTrueCompanyName(trueCompanyName);//当前登录用户所属公司全称
                }
            }
        }
        return queryVO;
    }

    @Override
    public String deleteByFlowId(String flowId) {
        //查询是否存在关联数据
        BankOrderExample bankOrderExample = new BankOrderExample();
        bankOrderExample.createCriteria().andFlowIdEqualTo(flowId);
        List<BankOrder> bankOrderList = bankOrderMapper.selectByExample(bankOrderExample);
        if (bankOrderList != null && bankOrderList.size() > 0) {
            return ResponseCodeEnum.DELETE_BANK_ERROR.getResponseCode();
        }
        BankFlow bankFlow = bankFlowDbService.selectByFlowId(flowId);
        String transactionDate = bankFlow.getTransactionDate();
        //查询数据库的到款日期限制天数
        int termDays = bankFlowDbService.getReturnMoneyDayNum();
        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, -termDays);
        Date date = c.getTime();
        String preDay = DateUtil.formatDate(date, "yyyy-MM-dd");
        //校验交易日期时间是否在系统配置时间之内
        if (transactionDate.compareTo(preDay) < 0) {
            return ResponseCodeEnum.BANK_TRANSACTIONDATE_RANGE_ERROR.getResponseCode();
        }
        //修改流水表的操作标识为del
        bankFlow.setOperateFlag("del");
        if (bankFlowDbService.updateByPrimaryKeySelective(bankFlow) <= 0) {
            return ResponseCodeEnum.DELETE_BANK_FAIL.getResponseCode();
        }
        return ResponseCodeEnum.OK.getResponseCode();
    }


    @Override
    public String insertBankFlow(BankImportModel model) {
        String transactionNo = model.getTransactionNo();
        String transactionDate = model.getTransactionDate();
        String creditMoney = model.getCreditMoney();//金额（可能有逗号）
        if (StringUtils.isNotBlank(creditMoney)) {
            creditMoney = revertMoney(creditMoney).toString();//转换成数值
        }
        BankFlow bankFlow = new BankFlow();
        String payeeName = model.getPayeeName();
        //必填项校验
        if (StringUtils.isBlank(transactionNo) || StringUtils.isBlank(transactionDate) || StringUtils.isBlank(model.getPayeeAcount())
                || StringUtils.isBlank(payeeName) || StringUtils.isBlank(model.getOppositeCompany())
                || StringUtils.isBlank(creditMoney) || StringUtils.isBlank(model.getCompanyName())) {
            return ResponseCodeEnum.PARAMETER_ERROR.getResponseCode();
        }
        String companyName = model.getCompanyName();
        SysCompany sysCompany = companyService.selectSysCompanyByCompanyName(companyName);
        //校验公司名称是否存在
        if (sysCompany == null) {
            //分公司不存在
            return ResponseCodeEnum.COMPANY_NAME_NOT_EXSIT.getResponseCode();
        }
        String companyId = sysCompany.getCompanyId();
        String trueCompanyName = "";//总公司默认当前公司名称是空
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        //3-总公司财务，除了3都是分公司账号
        if (!"3".equals(userAccount.getDeptId())) {
            //分公司
            SysCompany branchCompany = companyService.selectSysCompanyById(userAccount.getCompanyId());
            String branchCompanyName = branchCompany.getCompanyName();
            trueCompanyName = branchCompany.getTrueCompanyName();//公司全称（分公司的收款方名称）
            if (!branchCompanyName.equals(model.getCompanyName())) {
                //分公司只能录入自己公司的
                return ResponseCodeEnum.BANK_RELATE_COMPANY_ERROR.getResponseCode();
            }
        }
        //判断 收款方名称
        if (!checkExistPayeeName(model.getPayeeName(), trueCompanyName)) {
            return ResponseCodeEnum.ARRIVE_ACCOUNT_TYPE_NOT_EXSIT.getResponseCode();
        }
        if (StringUtils.isNotBlank(transactionNo)) {
            bankFlow.setTransactionNo(model.getTransactionNo());
        }
        if (StringUtils.isNotBlank(transactionDate)) {
            //判断交易日期是否符合yyyy-MM-dd HH:mm:ss格式
            if (!DateUtil.isDateTimeVail(transactionDate)) {
                return ResponseCodeEnum.BANK_TRANSACTIONDATE_ERROR.getResponseCode();
            } else {
                //查询数据库的到款日期限制天数
                int termDays = bankFlowDbService.getReturnMoneyDayNum();
                Calendar c = Calendar.getInstance();
                c.add(Calendar.DATE, -termDays);
                Date date = c.getTime();
                String preDay = DateUtil.formatDate(date, "yyyy-MM-dd");
                //判断 交易日期是否 >= 当前日期 -（数据库里的到款日期天数）
                if (transactionDate.compareTo(preDay) < 0) {
                    return ResponseCodeEnum.RNTURN_MONEY_EXIST.getResponseCode();
                }
                bankFlow.setTransactionDate(transactionDate);
            }
        }
        if (StringUtils.isNotBlank(model.getPayeeAcount())) {//收款方账号
            bankFlow.setPayeeAcount(model.getPayeeAcount());
        }
        if (StringUtils.isNotBlank(payeeName)) {//收款方名称
            bankFlow.setPayeeName(payeeName);
        }
        if (StringUtils.isNotBlank(model.getOppositeCompany())) {//对方单位名称
            bankFlow.setOppositeCompany(model.getOppositeCompany());
        }
        if (StringUtils.isNotBlank(creditMoney)) {//贷方金额
            bankFlow.setCreditMoney(revertMoney(creditMoney));
            bankFlow.setAvailableAmount(revertMoney(creditMoney));//默认可用金额和导入的贷方金额一致
            bankFlow.setUsedAmount(new BigDecimal(0));//默认已用金额是0
        }
        //根据transaction_no（交易流水号）、交易日期、金额 查询数据库是否存在
        boolean existTransactioNo = bankFlowDbService.existTransactioNo(transactionNo, transactionDate, creditMoney);
        if (existTransactioNo) {
            return ResponseCodeEnum.BANK_IS_EXSIT.getResponseCode();
        }
        if (StringUtils.isNotBlank(model.getAbstracts())) {
            bankFlow.setAbstracts(model.getAbstracts());
        }
        if (StringUtils.isNotBlank(model.getOppositeBank())) {
            bankFlow.setOppositeBank(model.getOppositeBank());
        }
        if (StringUtils.isNotBlank(model.getOppositeBankAccount())) {
            bankFlow.setOppositeBankAccount(model.getOppositeBankAccount());
        }
        bankFlow.setRelationState("N");//默认为N-未关联
        bankFlow.setCreatePeopleId(userAccount.getAccountId());//创建人
        bankFlow.setCreatePeopleName(userAccount.getUserName());//创建人名称
        bankFlow.setFlowId(CommonUtils.getGUID());//主键id
        bankFlow.setCompanyName(companyName);//所属分公司名称
        bankFlow.setCompanyId(companyId);//所属分公司id
        bankFlow.setOperateFlag("ok");//操作标识 ok-正常
        bankFlowDbService.insertBankFlow(bankFlow);
        return ResponseCodeEnum.OK.getResponseCode();
    }


    /**
     * 通过订单编号的公司，流水号查询流水可用余额
     *
     * @param serial
     * @param companyId
     * @return
     */
    @Override
    public BigDecimal selectCountAvailableAmount(String serial, String companyId) {
        return bankFlowDbService.selectCountAvailableAmount(serial, companyId);
    }

    /**
     * 根据流水号查询流水信息
     *
     * @param serial
     * @return
     */
    @Override
    public List<BankFlow> selectByTransactionNo(String serial, String orderId) {
        CustomerProductOrder order = orderDbService.selectProductOrderById(orderId);
        return bankFlowDbService.selectByTransactionNo(serial, order.getAffiliationCompanyId());
    }

    @Override
    public boolean exportBankFlowData(String sortName, String sortOrder, BankFlowQO bankFlowQO, ServletOutputStream outputStream) throws IOException {
        DhPageInfo<BankFlowQueryVO> bankFlowVODhPageInfo = this.queryBankFlowData(1, 5000, sortName, sortOrder, bankFlowQO);
        List<BankFlowQueryVO> bankFlowList = bankFlowVODhPageInfo.getList();
//        if(bankFlowList== null || bankFlowList.size()<=0){
//            return false;
//        }
        List<BankFlowExportVO> exportList = new ArrayList<>();
        for (BankFlowQueryVO vo : bankFlowList) {
            vo.setPayeeName(vo.getOldPayeeName());
            BankFlowExportVO exportInfo = new BankFlowExportVO();
            BeanUtils.copyProperties(vo, exportInfo);
            exportInfo.setCreditMoney(vo.getCreditMoney() == null ? "" : vo.getCreditMoney().toString());
            exportInfo.setCreditMoney(vo.getCreditMoney() + "");

            exportList.add(exportInfo);
        }
        if (bankFlowList == null || bankFlowList.size() <= 0) {
            exportList.add(new BankFlowExportVO());
        }
        Map map = new HashMap<>();
        map.put("银行流水", exportList);
        try {
            EasyExcelUtil.writeExcel(map, outputStream);
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
        }
        return true;
    }


    @Transactional
    @Override
    public String subAvailableAmount(String flowId, BigDecimal modifyMoney, String modifyReason) {
        if (StringUtils.isBlank(flowId) || StringUtils.isBlank(modifyMoney.toString()) || StringUtils.isBlank(modifyReason)) {
            return ResponseCodeEnum.PARAMETER_MISSING.getResponseCode();
        }
        BankFlow bankFlow = bankFlowDbService.selectByFlowId(flowId);
        BigDecimal oldAvailableAmount = bankFlow.getAvailableAmount();
        if (modifyMoney.compareTo(oldAvailableAmount) > 0) {
            return ResponseCodeEnum.SUB_AVAILABLEAMOUNT_ERROR.getResponseCode();
        }
        BigDecimal newAvailableAmount = oldAvailableAmount.subtract(modifyMoney);
        BigDecimal newUsedAmount = bankFlow.getUsedAmount().add(modifyMoney);
        //更新流水表的 可用金额 已用金额
        bankFlow.setUsedAmount(newUsedAmount);
        bankFlow.setAvailableAmount(newAvailableAmount);
        if (newAvailableAmount.compareTo(BigDecimal.ZERO) == 0) {
            //如果可用金额为0 则关联状态为 已关联
            bankFlow.setRelationState("Y");
        } else {
            bankFlow.setRelationState("B");//部分关联
        }
        bankFlowDbService.updateByPrimaryKeySelective(bankFlow);
        UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();//当前登录人信息
        //操作记录表插入一条记录
        ReturnMoneyLog operatorLog = new ReturnMoneyLog();
        operatorLog.setReturnMoneyLogId(CommonUtils.getGUID());
        operatorLog.setFlowId(flowId);
        operatorLog.setFormerData("原来的可用金额：" + oldAvailableAmount + "，本次调减金额：" + modifyMoney);
        operatorLog.setNewData("调减后的可用金额：" + newAvailableAmount);
        operatorLog.setOperatorType(5);//调减
        operatorLog.setModifyReason(modifyReason);//调减原因
        operatorLog.setCreateTm(new Date());
        operatorLog.setCreatePeopleId(userAccount.getAccountId());
        returnMoneyLogMapper.insertSelective(operatorLog);
        return ResponseCodeEnum.OK.getResponseCode();
    }


}
